package com.wlyuan.open.scanner.utils;

import com.wlyuan.open.scanner.utils.enums.user.UserRoleEnum;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 解析roleIDs,获取对应的单个id
 *
 * @author CaiCH
 * @date 2018/04/03 14:46
 **/

public class RoleIdsUtils {

    /**
     * 存储符合条件的数组元素下表
     */
    private static List<Integer> findNumIndex;

    /**
     * 是否可以从数组中找到相加等于“和”的元素
     */
    private static boolean findon;

    /**
     * 数组中是否有某个元素等于“和”本身
     */
    private static boolean someoneEqualSum;

    /**
     * 数组
     */
    private final static Integer[] ARRAY_INIT = {0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192};
    // private final static Integer[] A =
    // {1,2,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,131072,262144,524288,1048576,2097152};

    private final static List<Long> SKIP_LIST = Arrays.asList(4L, 16L, 64L, 2048L, 4096L);

    /**
     * 和
     */
    private static int sum;

    /**
     * 2
     */
    private final static Integer TWO = 2;

    private static List<String> roleIdList = null;
    private static List<Long> roleIdLongList = null;
    private static List<Long> newRoleIdLongList = null;

    public RoleIdsUtils(int sum) {
        RoleIdsUtils.sum = sum;
        findon = false;
        findNumIndex = new ArrayList<Integer>();
        someoneEqualSum = false;
    }

    private void start() {
        List<Integer> list = new LinkedList<Integer>();
        // 把int数组付给list
        for (int i = 0; i < ARRAY_INIT.length; i++) {
            list.add(ARRAY_INIT[i]);
        }
        boolean flag = true;
        do {
            // 当前最小值
            int mix = list.get(0);
            // 当前最大值
            int max = list.get(list.size() - 1);
            // 找到等于“和”的元素,做个标记
            if (max == sum) {
                someoneEqualSum = true;
            }
            // 移除未用的最大值
            if (mix + max > sum && flag) {
                list.remove(list.size() - 1);
            } else {
                flag = false;
            }
        } while (flag);
        startMath(list, sum);
    }

    private void startMath(List<Integer> list, int sum) {
        for (int i = 0; i <= list.size() - TWO; i++) {
            findNumIndex.clear();
            // 记录第一个元素坐标
            findNumIndex.add(list.size() - 1 - i);
            // 从最大的元素开始，依次往前推
            int indexNum = list.get(list.size() - 1 - i);
            action(list, indexNum, list.size() - 1 - i, sum);
        }
    }

    /**
     * 递归方法
     *
     * @param list     被查询的数组
     * @param indexsum 当前元素相加的和
     * @param index    下一个元素位置
     * @param sum      要匹配的和
     */
    private void action(List<Integer> list, int indexsum, int index, int sum) {
        if (index == 0) {
            return;
        }
        // 元素index-1太大了，跳到下一个元素继续遍历
        if (indexsum + list.get(index - 1) > sum) {
            action(list, indexsum, index - 1, sum);
            // 元素index-1可能符合条件，继续往下找
        } else if (indexsum + list.get(index - 1) < sum) {
            // 记录此元素坐标
            findNumIndex.add(index - 1);
            // 更新元素的和
            indexsum = indexsum + list.get(index - 1);
            action(list, indexsum, index - 1, sum);
        } else if (indexsum + list.get(index - 1) == sum) {
            findNumIndex.add(index - 1);
            findon = true;
            for (int a : findNumIndex) {
                if (list.get(a) != 0) {
                    roleIdList.add(list.get(a).toString());
                    roleIdLongList.add(Long.valueOf(list.get(a)));
                }
            }
            return;
        }
    }

    private void convert() {
        //手动剔除解析出来的新系统中没有对应的角色id
        roleIdLongList = roleIdLongList.stream().filter(roleId -> !SKIP_LIST.contains(roleId)).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(roleIdLongList)) {
            roleIdLongList.stream().forEach(roleId -> {
                Optional.ofNullable(UserRoleEnum.fromValue(roleId.intValue())).ifPresent(newRole -> {
                    newRoleIdLongList.addAll(newRole.getNewValue());
                });
            });
            //1024解析成10 11 ， 可能存在重复
            newRoleIdLongList = newRoleIdLongList.stream().distinct().collect(Collectors.toList());
        }
    }

    public static List<String> getRoleIdList(Integer roleIds) {
        roleIdList = new ArrayList<>();
        roleIdLongList = new ArrayList<>();
        RoleIdsUtils s = new RoleIdsUtils(roleIds);
        s.start();
        return roleIdList;
    }

    public static List<Long> getRoleIdLongList(Integer roleIds) {
        roleIdList = new ArrayList<>();
        roleIdLongList = new ArrayList<>();
        newRoleIdLongList = new ArrayList<>();
        RoleIdsUtils s = new RoleIdsUtils(roleIds);
        s.start();
        s.convert();
        return newRoleIdLongList;
    }

}
